package com.taoym.voucher.xcx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.taoym.voucher.common.constant.CommonConstant;
import com.taoym.voucher.common.enums.ActivityOrderStatusEnum;
import com.taoym.voucher.common.enums.OrderIsStatisticsBillEnum;
import com.taoym.voucher.common.enums.UserWithdrawStatusEnum;
import com.taoym.voucher.common.response.ResponseStatusCode;
import com.taoym.voucher.common.utils.ExceptionCore;
import com.taoym.voucher.common.utils.ThreadLocalUtils;
import com.taoym.voucher.common.utils.ThreadPoolUtils;
import com.taoym.voucher.common.utils.TimeUtil;
import com.taoym.voucher.xcx.domain.XcxActivityOrder;
import com.taoym.voucher.xcx.domain.XcxUserWithdraw;
import com.taoym.voucher.xcx.entity.vo.XcxGetUserWithdrawVO;
import com.taoym.voucher.xcx.mapper.XcxActivityOrderMapper;
import com.taoym.voucher.xcx.mapper.XcxUserWithdrawMapper;
import com.taoym.voucher.xcx.message.MyMailSender;
import com.taoym.voucher.xcx.service.SysUserService;
import com.taoym.voucher.xcx.service.XcxActivityOrderService;
import com.taoym.voucher.xcx.service.XcxUserWithdrawService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;

/**
 * @coder taoym
 * @datetime 2021/5/24 22:06
 * @desc 提现接口服务实现类
 */
@Service
@Slf4j
public class XcxUserWithdrawServiceImpl implements XcxUserWithdrawService {

    @Resource
    private XcxUserWithdrawMapper xcxUserWithdrawMapper;
    @Resource
    private XcxActivityOrderMapper xcxActivityOrderMapper;
    @Autowired
    private XcxActivityOrderService xcxActivityOrderService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private MyMailSender myMailSender;

    /**
     * 申请提现功能
     * 先把没有统计且状态为已结算的订单查询出来
     * 然后计算团长的佣金总数
     * 然后将佣金信息和团长信息保存到
     * 提现表，
     * 然后更新订单的统计状态
     * 最后通过小程序消息通知管理员
     * 每个月的20-30号可以提现上个月及之前的所有订单
     */
    @Override
    @Transactional
    public Boolean applyUserWithdraw() {

        int day = LocalDateTime.now().getDayOfMonth();
        if (day < 30 && day > 20) {
            throw new ExceptionCore(ResponseStatusCode.PLEASE_WITHDRAW_ON_TIME);
        }
        LocalDateTime prevMonthEnd = TimeUtil.getMonthEndTime(LocalDate.now().plusMonths(-1));

        String uid = ThreadLocalUtils.get().getUid();
        // 查询自购订单
        List<XcxActivityOrder> myActivityOrders = xcxActivityOrderMapper.selectList(new QueryWrapper<XcxActivityOrder>()
                .select("id", "order_user_fee")
                .eq("order_user_uid", uid)
                .eq("status", ActivityOrderStatusEnum.IS_SETTLEMENT.getCode())
                .eq("order_user_is_statistics", OrderIsStatisticsBillEnum.NO.getCode())
                .lt("modified_time", prevMonthEnd));
        // 查询团队订单
        List<XcxActivityOrder> teamActivityOrders = xcxActivityOrderMapper.selectList(new QueryWrapper<XcxActivityOrder>().select("id", "chief_fee")
                .eq("chief_uid", uid)
                .eq("status", ActivityOrderStatusEnum.IS_SETTLEMENT.getCode())
                .eq("chief_is_statistics", OrderIsStatisticsBillEnum.NO.getCode())
                .lt("modified_time", prevMonthEnd));

        // 自购订单佣金
        BigDecimal orderUserFee = new BigDecimal("0");
        if (!CollectionUtils.isEmpty(myActivityOrders)) {
            orderUserFee = myActivityOrders.stream().map(s -> new BigDecimal(s.getOrderUserFee()))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        // 团队订单佣金
        BigDecimal chiefFee = new BigDecimal("0");
        if (!CollectionUtils.isEmpty(teamActivityOrders)) {
            chiefFee = myActivityOrders.stream().map(s -> new BigDecimal(s.getChiefFee()))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        // 总佣金
        BigDecimal allFee = orderUserFee.add(chiefFee);

        if (allFee.compareTo(new BigDecimal(CommonConstant.WITHDRAW)) <= 0) {
            throw new ExceptionCore(ResponseStatusCode.FEE_IS_NOT_ENOUGH);
        }

        XcxUserWithdraw xcxUserWithdraw = new XcxUserWithdraw();
        xcxUserWithdraw.setApplyTime(LocalDateTime.now());
        xcxUserWithdraw.setAmount(allFee.toString());
        xcxUserWithdraw.setUid(uid);
        xcxUserWithdraw.setStatus(UserWithdrawStatusEnum.IS_APPLY.getCode());

        xcxUserWithdrawMapper.insert(xcxUserWithdraw);

        // 修改自购订单的统计状态状态
        myActivityOrders.forEach(e -> {
            e.setOrderUserIsStatistics(OrderIsStatisticsBillEnum.YES.getCode());
        });
        // 修改团队订单的统计状态
        teamActivityOrders.forEach(e -> {
            e.setChiefIsStatistics(OrderIsStatisticsBillEnum.YES.getCode());
        });

        boolean b = xcxActivityOrderService.updateBatchById(myActivityOrders);
        boolean b1 = xcxActivityOrderService.updateBatchById(teamActivityOrders);

        // 使用线程池 异步发送，目前使用的是邮件的方式
        ExecutorService executorService = ThreadPoolUtils.getExecutorService();
        executorService.submit(() -> {
            myMailSender.send("生活遇券", "提现申请", sysUserService.getSysUser().getEmail());
        });
        return b;
    }

    @Override
    public List<XcxGetUserWithdrawVO> getMyWithdraws() {
        String uid = ThreadLocalUtils.get().getUid();

        List<XcxUserWithdraw> userWithdraws = xcxUserWithdrawMapper.selectList(new QueryWrapper<XcxUserWithdraw>()
                .select("id", "amount", "apply_time", "status", "remark")
                .eq("uid", uid));

        if (CollectionUtils.isEmpty(userWithdraws)) {
            return null;
        }

        List<XcxGetUserWithdrawVO> xcxGetUserWithdrawVOS = new ArrayList<>(userWithdraws.size());
        userWithdraws.forEach(e -> {
            XcxGetUserWithdrawVO xcxGetUserWithdrawVO = new XcxGetUserWithdrawVO();
            xcxGetUserWithdrawVO.setAmount(e.getAmount());
            xcxGetUserWithdrawVO.setId(e.getId());
            xcxGetUserWithdrawVO.setApplyTime(e.getApplyTime());
            xcxGetUserWithdrawVO.setRemark(e.getRemark());
            xcxGetUserWithdrawVO.setColor(UserWithdrawStatusEnum.getColor(e.getStatus()));
            xcxGetUserWithdrawVO.setStatus(UserWithdrawStatusEnum.getMsg(e.getStatus()));

            xcxGetUserWithdrawVOS.add(xcxGetUserWithdrawVO);
        });
        return xcxGetUserWithdrawVOS;
    }
}


